package com.panopset.gui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import static com.panopset.Util.*;

/**
 * Spins off a new Thread, which calls the abstract run method of this class.
 * That run method should check the isHaltRequested value in each major loop,
 * and exit cleanly if that value is true.
 *
 * @author Karl Dinwiddie
 *
 */
public abstract class ThreadButton {

    /**
     * Thread.
     */
    private Thread t;

    /**
     * Is halt requested flag.
     */
    private boolean isHaltRequested;

    /**
     * This needs to be checked in each major loop iteration of the overridden
     * run method.
     *
     * @return True if halt has been requested.
     */
    public final boolean isHaltRequested() {
        return isHaltRequested;
    }

    /**
     * The button.
     */
    private TButton btn;

    /**
     * Override this method to provide the function to be run in a thread, in
     * response to the button being selected.
     */
    public abstract void run();

    /**
     * @return Text for the button.
     */
    public abstract String createText();

    /**
     * @return Tool tip text for the button.
     */
    public abstract String createTipText();

    /**
     * @return Mnemonic for the button.
     */
    public abstract char createMnemonic();

    /**
     * @return Thread name.
     */
    public abstract String createThreadName();

    /**
     * @return Button gui.
     */
    public final TButton getGui() {
        if (this.btn == null) {
            this.btn = new TButton(getText(), getTipText());
            this.btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(final ActionEvent e) {
                    doRun();
                }
            });
        }
        return this.btn;
    }

    /**
     * Do run.
     */
    private void doRun() {
        if (t == null) {
            getGui().setText(x("Cancel"));
            getGui().setMnemonic(KeyEvent.VK_C);
            t = new Thread(getThreadName()) {
                @Override
                public synchronized void run() {
                    isHaltRequested = false;
                    ThreadButton.this.run();
                    getGui().setText(getText());
                    getGui().setMnemonic(getMnemonic());
                    t = null;
                }
            };
            t.start();
        } else {
            isHaltRequested = true;
        }
    }

    /**
     * Text.
     */
    private String text;

    /**
     * @return Text.
     */
    private String getText() {
        if (this.text == null) {
            this.text = createText();
        }
        return this.text;
    }

    /**
     * Tool tip text.
     */
    private String tipText;

    /**
     * @return Tool tip text.
     */
    private String getTipText() {
        if (this.tipText == null) {
            this.tipText = createTipText();
        }
        return this.tipText;
    }

    /**
     * Mnemonic.
     */
    private Character mnemonic;

    /**
     * @return Mnemonic.
     */
    private Character getMnemonic() {
        if (this.mnemonic == null) {
            this.mnemonic = Character.valueOf(createMnemonic());
        }
        return this.mnemonic;
    }

    /**
     * Thread name.
     */
    private String threadName;

    /**
     * @return Thread name.
     */
    private String getThreadName() {
        if (this.threadName == null) {
            this.threadName = createThreadName();
        }
        return this.threadName;
    }
}
